﻿//MarketDataGrid.xaml.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Xaml
{
	using System;
	using System.Collections.Generic;
	using System.Collections.ObjectModel;
	using System.Linq;
	using System.Windows.Data;
	using System.Windows.Media;

	using Ecng.Collections;
	using Ecng.ComponentModel;
	using Ecng.Serialization;
	using Ecng.Xaml.Grids;

	using StockSharp.Algo;
	using StockSharp.Algo.Storages;
	using StockSharp.BusinessEntities;

	/// <summary>
	/// Таблица доступных рыночных данных.
	/// </summary>
	public partial class MarketDataGrid : IPersistable
	{
		private sealed class MarketDataEntry : NotifiableObject
		{
			public MarketDataEntry(DateTime date)
			{
				Date = date;
			}

			public DateTime Date { get; set; }

			public int Year { get { return Date.Year; } }

			public int Month { get { return Date.Month; } }

			public int Day { get { return Date.Day; } }

			public bool IsDepthDownloaded { get; set; }

			public bool IsTickDownloaded { get; set; }

			public bool IsOrderLogDownloaded { get; set; }

			public bool IsChangesDownloaded { get; set; }
		}

		private readonly ObservableCollection<MarketDataEntry> _entries = new ObservableCollection<MarketDataEntry>();

		/// <summary>
		/// Создать <see cref="MarketDataGrid"/>.
		/// </summary>
		public MarketDataGrid()
		{
			InitializeComponent();

			Grid.Data = _entries;

			for (var i = 3; i < Grid.Columns.Count; i++)
			{
				Grid.FormatRules.Add(Grid.Columns[i], new FormatRule
				{
					Type = FormatRuleTypes.PropertyValue,
					Value = true,
					Condition = ComparisonOperator.Equal,
					Background = Brushes.LightGreen,
				});

				Grid.FormatRules.Add(Grid.Columns[i], new FormatRule
				{
					Type = FormatRuleTypes.PropertyValue,
					Value = false,
					Condition = ComparisonOperator.Equal,
					Background = Brushes.Pink,
				});
			}

			Grid.ApplyFormatRules();

			Grid.ShowHeaderInGroupTitle = false;
			Grid.GroupingMemberConverters.Add("Month", (IValueConverter)Resources["monthToNameConverter"]);

			Grid.GroupingMembers.Add("Year");
			Grid.GroupingMembers.Add("Month");
		}

		/// <summary>
		/// Хранилище маркет-данных.
		/// </summary>
		public IStorageRegistry StorageRegistry { get; set; }

		private Security _security;

		/// <summary>
		/// Инструмент.
		/// </summary>
		public Security Security
		{
			get { return _security; }
			set
			{
				_security = value;
				MakeEntries();
			}
		}

		private void MakeEntries()
		{
			_entries.Clear();

			if (Security == null)
				return;

			if (StorageRegistry == null)
				throw new InvalidOperationException("Хранилище маркет-данных не инициализировано.");

			var dic = new Dictionary<DateTime, MarketDataEntry>();

			Add(dic, StorageRegistry.GetTradeStorage(Security), e => e.IsTickDownloaded = true);
			Add(dic, StorageRegistry.GetMarketDepthStorage(Security), e => e.IsDepthDownloaded = true);
			Add(dic, StorageRegistry.GetSecurityChangeStorage(Security), e => e.IsChangesDownloaded = true);
			Add(dic, StorageRegistry.GetOrderLogStorage(Security), e => e.IsOrderLogDownloaded = true);

			if (dic.Count > 0)
			{
				GetDateRange(dic.Keys.Min(), dic.Keys.Max())
					.Where(d => Security.ExchangeBoard.WorkingTime.IsTradeDate(d, true) && !dic.ContainsKey(d))
					.ForEach(date => dic.SafeAdd(date, d => new MarketDataEntry(d)));
			}

			_entries.AddRange(dic.Values.OrderBy(v => v.Date));
		}

		private static void Add(IDictionary<DateTime, MarketDataEntry> dic, IMarketDataStorage storage, Action<MarketDataEntry> action)
		{
			storage
				.Dates
				.Select(date => dic.SafeAdd(date, d => new MarketDataEntry(d)))
				.ForEach(action);
		}

		private static IEnumerable<DateTime> GetDateRange(DateTime startDate, DateTime endDate)
		{
			while (startDate <= endDate)
			{
				yield return startDate;
				startDate = startDate.AddDays(1);
			}
		}

		void IPersistable.Load(SettingsStorage storage)
		{
			Grid.Load(storage.GetValue<SettingsStorage>("Grid"));
		}

		void IPersistable.Save(SettingsStorage storage)
		{
			storage.SetValue("Grid", Grid.Save());
		}
	}
}